﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.IO;
using System.IO.IsolatedStorage;
using ArgusControls;
using ArgusLight.Fractals2D;

namespace Fractals
{
	public enum FavoritesWindowMode
	{
		Open,
		Save
	}

	class FavTreeViewItem : ImageTreeViewItem
	{
		public string Path { get; set; }
	}

	public partial class FavoritesWindow : ChildWindow
	{
		public FavoritesWindowMode Mode { get; private set; }
		public FractalSaveStruct StorageStruct { get; private set; }

		static readonly Size PreviewSize = new Size(50, 50);

		List<string> lDirectories;
		List<string> lFiles;
		Dictionary<Fractal, FavTreeViewItem> dictFracts;

		public FavoritesWindow()
		{
			InitializeComponent();
			this.StorageStruct = new FractalSaveStruct();
		}

		private new void Show()
		{
			base.Show();
		}

		public void ShowSaveDialog(Fractal fractal)
		{
			this.Mode = FavoritesWindowMode.Save;
			this.StorageStruct = new FractalSaveStruct(fractal);
			this.tbRename.IsEnabled = true;
			this.bSave.Visibility = System.Windows.Visibility.Visible;
			this.bOpen.Visibility = System.Windows.Visibility.Collapsed;
			this.Show();
		}

		public void ShowOpenDialog()
		{
			this.Mode = FavoritesWindowMode.Open;
			this.tbRename.IsEnabled = false;
			this.bSave.Visibility = System.Windows.Visibility.Collapsed;
			this.bOpen.Visibility = System.Windows.Visibility.Visible;
			this.bOpen.IsEnabled = false;
			this.Show();
		}

		protected override void OnOpened()
		{
			base.OnOpened();
			this.lDirectories = new List<string>();
			this.lFiles = new List<string>();
			this.dictFracts = new Dictionary<Fractal, FavTreeViewItem>();
			this.treeView.Items.Clear();
			using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
			{
				string[] directories = store.GetDirectoryNames(Path.Combine(IsolatedDirectories.Favorites,"*"));
				foreach (string dir in directories)
				{
					string path = Path.Combine(IsolatedDirectories.Favorites, dir);
					this.lDirectories.Add(path);
					FavTreeViewItem tvi = GetDirectoryTVI(dir, store);
					tvi.KeyDown += tvi_KeyDown;
					tvi.Path = path;
					this.treeView.Items.Add(tvi);
				}

				string[] files = store.GetFileNames(Path.Combine(IsolatedDirectories.Favorites, "*"));
				foreach (string file in files)
				{
					string path = Path.Combine(IsolatedDirectories.Favorites, file);
					this.lFiles.Add(path);
					FavTreeViewItem tvi = new FavTreeViewItem();
					tvi.HeaderText = file;
					tvi.Path = path;
					tvi.KeyDown += tvi_KeyDown;
					this.treeView.Items.Add(tvi);


					FractalSaveStruct str;
					bool RewriteNewFormat = false;
					using (IsolatedStorageFileStream fileStream = store.OpenFile(path, FileMode.Open))
					{
						RewriteNewFormat = FractalSaveStruct.IsOldFormat(fileStream);
						str = FractalSaveStruct.FromStream(fileStream);
						fileStream.Close();
						this.CalculatePreviewImage(str, tvi);
					}

					if (RewriteNewFormat == true)
					{
						using (IsolatedStorageFileStream FileStream = store.OpenFile(path, FileMode.Create))
						{
							str.Save(FileStream);
							FileStream.Close();
						}
					}
				}

				if (this.Mode == FavoritesWindowMode.Save)
				{
					List<string> pFiles = new List<string>(files);
					string name = Localization.Text.FavoritesWindowStandardSaveName;
					int i = 0;
					while (pFiles.Contains(name) == true)
					{
						i++;
						name = Localization.Text.FavoritesWindowStandardSaveName + i.ToString();
					}
					this.tbRename.Text = name;
				}
			}
		}

		private FavTreeViewItem GetDirectoryTVI(string dir, IsolatedStorageFile store)
		{
			FavTreeViewItem tvi = new FavTreeViewItem();
			tvi.HeaderText = dir;
			string[] directories = store.GetDirectoryNames(Path.Combine(dir, "*"));
			foreach (string d in directories)
			{
				string path = Path.Combine(dir, d);
				this.lDirectories.Add(path);
				FavTreeViewItem temp = GetDirectoryTVI(d, store);
				temp.KeyDown += tvi_KeyDown;
				temp.Path = path;
				tvi.Items.Add(temp);
			}

			string[] files = store.GetFileNames(Path.Combine(dir, "*"));
			foreach (string file in files)
			{
				string path = Path.Combine(dir, file);
				this.lFiles.Add(path);
				FavTreeViewItem tviFile = new FavTreeViewItem();
				tviFile.HeaderText = file;
				tviFile.Path = path;
				tviFile.KeyDown += tvi_KeyDown;
				tvi.Items.Add(tviFile);

				using (IsolatedStorageFileStream fileStream = store.OpenFile(path, FileMode.Open))
				{
					FractalSaveStruct str = FractalSaveStruct.FromStream(fileStream);
					this.CalculatePreviewImage(str, tvi);
				}
			}
			return tvi;
		}

		private void bSave_Click(object sender, RoutedEventArgs e)
		{
			string path = string.Empty;
			if (this.treeView.SelectedItem == null)
				path = Path.Combine(IsolatedDirectories.Favorites, this.tbRename.Text);
			else
			{
				path = ((FavTreeViewItem)this.treeView.SelectedItem).Path;
				if (this.lDirectories.Contains(path) == true)
				{
					path = Path.Combine(path, this.tbRename.Text);
				}
				else
				{
					int i = path.LastIndexOf(Path.DirectorySeparatorChar);
					if (i > -1)
					{
						path = Path.Combine(path.Substring(0, i), this.tbRename.Text);
					}
				}
			}

			Action<MessageBoxResults> a = result =>
				{
					if (result != MessageBoxResults.Yes)
						return;
					using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
					{
						using (IsolatedStorageFileStream file = store.CreateFile(path))
						{
							this.StorageStruct.Save(file);
							file.Close();
						}
					}

					this.DialogResult = true;
				};

			if (this.lFiles.Contains(path) == true)
			{
				ArgusControls.MessageBox.Show(
					Localization.Text.FavoritesWindowPromptOverwriteMessage,
					Localization.Text.FavoritesWindowPromptOverwriteCaption,
					MessageBoxButtons.YesNo,
					a);
			}
			else
			{
				a(MessageBoxResults.Yes);
			}
		}

		private void bOpen_Click(object sender, RoutedEventArgs e)
		{
			FavTreeViewItem tvi = null;
			if (this.treeView.SelectedItem != null)
				tvi = (FavTreeViewItem)this.treeView.SelectedItem;

			//if (tvi == null || this.lFiles.Contains(tvi.Path) == false)
			//{
			//	ArgusControls.MessageBox.Show(Localization.Text.FavoritesWindowPromptNoValidItem);
			//	return;
			//}

			using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
			{
				using (IsolatedStorageFileStream file = store.OpenFile(tvi.Path, FileMode.Open))
				{
					this.StorageStruct = FractalSaveStruct.FromStream(file);
					file.Close();
				}
			}
			this.DialogResult = true;
		}

		private void bCancel_Click(object sender, RoutedEventArgs e)
		{
			this.DialogResult = false;
		}

		private void treeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
		{
			if (this.treeView.SelectedItem != null)
			{
				FavTreeViewItem tvi = (FavTreeViewItem)this.treeView.SelectedItem;
				this.tbRename.Text = (string)tvi.HeaderText;
				if (this.lFiles.Contains(tvi.Path) == true)
					this.bOpen.IsEnabled = true;
				else
					this.bOpen.IsEnabled = false;
			}
			else
			{
				this.tbRename.Text = string.Empty;
				this.bOpen.IsEnabled = false;
			}
		}

		void tvi_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
		{
			FavTreeViewItem Sender = (FavTreeViewItem)sender;
			if (e.Key != System.Windows.Input.Key.Delete)
				return;

			Action<MessageBoxResults> a = result =>
				{
					if (result != MessageBoxResults.Yes)
						return;

					using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
					{
						if (this.lFiles.Contains(Sender.Path) == true)
						{
							store.DeleteFile(Sender.Path);
							this.lFiles.Remove(Sender.Path);
						}
						else if (this.lDirectories.Contains(Sender.Path) == true)
						{
							string[] files = store.GetFileNames(Path.Combine(Sender.Path, "*"));
							foreach (string file in files)
							{
								string filePath = Path.Combine(Sender.Path, file);
								store.DeleteFile(filePath);
								this.lFiles.Remove(filePath);
							}
							store.DeleteDirectory(Sender.Path);
							this.lDirectories.Remove(Sender.Path);
						}
					}

					if (Sender.Parent is TreeView)
						((TreeView)Sender.Parent).Items.Remove(Sender);
					else if (Sender.Parent is TreeViewItem)
						((TreeViewItem)Sender.Parent).Items.Remove(Sender);
				};

			ArgusControls.MessageBox.Show(
				Localization.Text.FavoritesWindowPromptDeleteMessage,
				Localization.Text.FavoritesWindowPromptDeleteCaption,
				MessageBoxButtons.OKCancel,
				a);
		}

		//public Fractal GetFractal()
		//{
		//	return this.GetFractal(this.StorageStruct);
		//}

		//private Fractal GetFractal(FractalStorageStruct str)
		//{
		//	if (this.Mode != FavoritesWindowMode.Open)
		//		return null;

		//	Fractal f = (Fractal)Activator.CreateInstance(str.FractalType);
		//	Coloring c = (Coloring)Activator.CreateInstance(str.ColoringType);
		//	c.Parameter = str.ColoringParameter;
		//	f.SetColoring(c);
		//	return f;
		//}

		private void CalculatePreviewImage(FractalSaveStruct str, FavTreeViewItem tvi)
		{
			Fractal fractal = str.GetFractal();
			fractal.CalculationFinished += fractal_CalculationFinished;
			this.dictFracts.Add(fractal, tvi);

			Size size = new Size(str.FractalParameter.PixelWidth, str.FractalParameter.PixelHeight);
			Size dest = PreviewSize.ChangeRatio(size.GetRatio(), System.Windows.ExtensionMethods.ChangeRatioOptions.DecreaseAreaSize);
			FractalParameter fPara = str.FractalParameter.GetCopy();
			fPara.PixelWidth = (int)dest.Width;
			fPara.PixelHeight = (int)dest.Height;

			fractal.StartCalculation(fPara);
		}

		void fractal_CalculationFinished(object sender, CalculationFinishedArgs e)
		{
			Fractal Sender = (Fractal)sender;
			FavTreeViewItem tvi;
			if (this.dictFracts.TryGetValue(Sender, out tvi) == true)
			{
				tvi.HeaderImage = Sender.GetImage();
			}
			this.dictFracts.Remove(Sender);
		}

		protected override void OnClosed(EventArgs e)
		{
			base.OnClosed(e);
			Dictionary<Fractal, FavTreeViewItem>.KeyCollection.Enumerator en = this.dictFracts.Keys.GetEnumerator();
			while (en.MoveNext() == true)
			{
				en.Current.RequestCalculationCancelation();
			}
		}
	}
}

